package com.jk.framework.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import com.jk.framework.DateTimeFormatHolder;
import com.jk.framework.jackson.LongJacksonSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Slf4j
@Configuration
public class JacksonConfig {


    @Primary
    @Bean
    public ObjectMapper objectMapper() {
        log.info("==== {}", ObjectMapper.class.getName());

        SimpleModule simpleModule = new SimpleModule();
        /*simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
            simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);*/
        simpleModule.addSerializer(Long.class, LongJacksonSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, LongJacksonSerializer.instance);


        return Jackson2ObjectMapperBuilder.json()
                // 重点,这是序列化LocalDateTIme和LocalDate的必要配置,由Jackson-data-JSR310实现
                .modules(
                        simpleModule,
                        new ParameterNamesModule(),

                        javaTimeModule()) // todo:add javaTimeModule
                // .featuresToEnable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
                // added at 20200327
                .featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                .featuresToDisable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)
                .featuresToDisable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
                .featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)

                // end added at 20200327
                .featuresToDisable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)
                .serializationInclusion(JsonInclude.Include.NON_NULL)
                // added at 20200808
                .visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
                .featuresToEnable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
                .build()
                //.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
                //.disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)
                // .setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CAMEL_CASE)
                ;
    }

    @Bean
    public JavaTimeModule javaTimeModule() {
        JavaTimeModule module = new JavaTimeModule();
        // SimpleModule module = new SimpleModule();
        module
                .addSerializer(Date.class, new DateSerializer(false, DateTimeFormatHolder.DATE_FORMATTER_YYYY_MM_DD_HH_MM_SS))
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatHolder.FORMATTER_YYYY_MM_DD_HH_MM_SS))
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatHolder.FORMATTER_YYYY_MM_DD_HH_MM_SS))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatHolder.FORMATTER_YYYY_MM_DD))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatHolder.FORMATTER_YYYY_MM_DD))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatHolder.FORMATTER_HH_MM_SS))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatHolder.FORMATTER_HH_MM_SS));
        return module;
    }
}
